package net.shouyong.jsserialize;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.serialize.ScriptableInputStream;
import org.mozilla.javascript.serialize.ScriptableOutputStream;

/**
 * @author shouyong
 * @version 1.0 at 2014-5-27
 * 
 */
public class MainFrame extends JFrame {

	private static final String PLEASE_SELECT_JSFILE = "Please select TextField to select js file.";

	private static final long serialVersionUID = -5083132777550910836L;
	private JTextField textField;
	private JTextArea jscontent;

	public MainFrame() {
		setTitle("Rhino Serialization JavaScript File.");
		setSize(500, 300);
		textField = new JTextField();
		textField.setText(PLEASE_SELECT_JSFILE);
		textField.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				chooseJSFile();
			}
		});
		getContentPane().add(textField, BorderLayout.NORTH);
		textField.setColumns(10);

		JButton btnNewButton = new JButton("Serialize/deSerialize");
		btnNewButton.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				// TODO action
				trySerialization(textField.getText().trim());
			}
		});
		getContentPane().add(btnNewButton, BorderLayout.SOUTH);

		jscontent = new JTextArea();
		JScrollPane jsContentScroll = new JScrollPane(jscontent);
		getContentPane().add(jsContentScroll, BorderLayout.CENTER);
		jscontent.setColumns(10);
	}

	protected void trySerialization(String attachmentFile) {
		JFileChooser chooser = new JFileChooser();
		chooser.setFileFilter(new FileNameExtensionFilter("JavaScript/SerializeJavaScript File",
				new String[] { "js", "ser" }));
		int flag = chooser.showSaveDialog(this);
		if (flag == JFileChooser.APPROVE_OPTION) {
			String path = chooser.getSelectedFile().getAbsolutePath();
			
			if(!serialization(attachmentFile,path)){
				JOptionPane.showMessageDialog(null, "保存失败");
			}
			
//			try {
//				FileInputStream ins = new FileInputStream(attachmentFile);
//				FileOutputStream out = new FileOutputStream(path);
//				byte b[] = new byte[512];
//				while ((ins.read(b)) > 0) {
//					out.write(b);
//				}
//				out.close();
//				ins.close();
//			} catch (IOException e2) {
//				JOptionPane.showMessageDialog(null, "保存失败");
//				e2.printStackTrace();
//			}
		}
	}

	protected void chooseJSFile() {
		jscontent.setText("");
		JFileChooser jf = new JFileChooser();
		jf.setFileFilter(new FileNameExtensionFilter("JavaScript File",
				new String[] { "js", "ser" }));
		jf.showOpenDialog(this);
		if (jf.getSelectedFile() == null) {
			return;
		}
		String jsfile = jf.getSelectedFile().getAbsolutePath();
		textField.setText(jsfile);
		
		if(jsfile.endsWith(".ser")){
			
			Object o = deSerialization(jsfile);
			runJSByObject(o);
			System.out.println(o.toString());
		}
		
		jscontent.setText(new String(readFileByBytes(jsfile)));
	}

	private void runJSByObject(Object o) {
		
		Context cx = ContextFactory.getGlobal().enterContext();
		cx.setOptimizationLevel(-1);
		cx.setLanguageVersion(Context.VERSION_1_5);
		Scriptable scope = cx.initStandardObjects(null);
//		scope.
		cx.evaluateString(scope, "", "", 1, null);		
	}

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				MainFrame mainFrame = new MainFrame();
				mainFrame.setVisible(true);
			}
		});
	}

	public boolean serialization(String srcJSPath, String savePath) {

		Context cx = ContextFactory.getGlobal().enterContext();
		cx.setOptimizationLevel(-1);
		cx.setLanguageVersion(Context.VERSION_1_5);
		Scriptable scope = cx.initStandardObjects(null);

		File fPath = new File(srcJSPath);

		FileOutputStream fos = null;
		ScriptableOutputStream out = null;
		try {
			Object obj = cx.evaluateReader(scope, new FileReader(fPath),
					fPath.getName(), 1, null);
			fos = new FileOutputStream(savePath);
			out = new ScriptableOutputStream(fos, scope);
			out.writeObject(obj);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
				}
			}
			Context.exit();
		}
		return false;
	}

	public Object deSerialization(String path) {

		Context cx = ContextFactory.getGlobal().enterContext();
		cx.setOptimizationLevel(-1);
		cx.setLanguageVersion(Context.VERSION_1_5);
		Scriptable scope = cx.initStandardObjects(null);

		FileInputStream fis = null;
		ScriptableInputStream in = null;
		Object deserialized = null;
		try {
			fis = new FileInputStream(path);
			in = new ScriptableInputStream(fis, scope);
			deserialized = in.readObject();
			in.close();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
				}
			}
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
				}
			}
		}
        return Context.toObject(deserialized, scope);
	}

	/**
	 * 
	 * @param fileName
	 * @return
	 */
	public static byte[] readFileByBytes(String fileName) {
		File file = new File(fileName);
		long l = file.length();
		int byte_length = 0;
		byte_length = (int) l;
		byte[] fileByte = new byte[byte_length];
		InputStream in = null;
		try {
			int byteread = 0;
			in = new FileInputStream(fileName);
			byteread = in.read(fileByte);
			if (byteread < 0) {
				return null;
			}
		} catch (Exception e1) {
			e1.printStackTrace();
			return null;
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e1) {
				}
			}
		}
		return fileByte;

	}

}
